# 数组变维操作  reshape  flat  flatten  ravel
# 数组转置操作  transpose  ndarray.T  rollaxis  swapaxes
# 修改数组维度操作  broadcast  broadcast_to  expand_dims  squeeze
# 连接与分割数组操作 concatenate stack hstack vstack split hsplit vsplit

# 数组变维操作
# reshape	在不改变数组元素的条件下，修改数组的形状。
# flat	返回是一个迭代器，可以用 for 循环遍历其中的每一个元素。
# flatten	以一维数组的形式返回一份数组的副本，对副本的操作不会影响到原数组。
# ravel	返回一个连续的扁平数组（即展开的一维数组），与 flatten不同，它返回的是数组视图（修改视图会影响原数组）。

import numpy as np

a = np.arange(9).reshape(3, 3)
for row in a:
    print(row)
# [0 1 2]
# [3 4 5]
# [6 7 8]

# 使用flat属性：
for ele in a.flat:
    print(ele, end="，")  # 0，1，2，3，4，5，6，7，8，

# 默认按行C风格展开的数组
print(a.flatten())  # [0 1 2 3 4 5 6 7 8]
# 以F风格顺序展开的数组
print(a.flatten(order='F'))  # [0 3 6 1 4 7 2 5 8]
print(a.ravel())  # [0 1 2 3 4 5 6 7 8]
print(a.ravel(order='F'))  # [0 3 6 1 4 7 2 5 8]

# 数组转置操作
# transpose	将数组的维度值进行对换，比如二维数组维度(2,4)使用该方法后为(4,2)。
# ndarray.T	与 transpose 方法相同。
# rollaxis	沿着指定的轴向后滚动至规定的位置。
# swapaxes	对数组的轴进行对换。
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
print(np.transpose(a))
# [[ 0  4  8]
#  [ 1  5  9]
#  [ 2  6 10]
#  [ 3  7 11]]

# 创建了三维的 ndarray
a = np.arange(27).reshape(3, 3, 3)
print(a)
# [[[ 0  1  2]
#   [ 3  4  5]
#   [ 6  7  8]]
#  [[ 9 10 11]
#   [12 13 14]
#   [15 16 17]]
#  [[18 19 20]
#   [21 22 23]
#   [24 25 26]]]
# 对换0轴与2轴
print(np.swapaxes(a, 2, 0))
# [[[ 0  9 18]
#   [ 3 12 21]
#   [ 6 15 24]]
#  [[ 1 10 19]
#   [ 4 13 22]
#   [ 7 16 25]]
#  [[ 2 11 20]
#   [ 5 14 23]
#   [ 8 17 26]]]


# 修改数组维度操作
# broadcast	生成一个模拟广播的对象。
# broadcast_to	将数组广播为新的形状。
# expand_dims	扩展数组的形状。
# squeeze	从数组的形状中删除一维项。

a = np.array([[1], [2], [3]])
b = np.array([4, 5, 6])
# 对b广播a
d = np.broadcast(a, b)
# d它拥有 iterator 属性
r, c = d.iters
print(next(r), next(c))  # 1 4
print(next(r), next(c))  # 1 5
# 使用broadcast将a与b相加
e = np.broadcast(a, b)
f = np.empty(e.shape)
f.flat = [x + y for (x, y) in e]
print(f)
# [[5. 6. 7.]
# [6. 7. 8.]
# [7. 8. 9.]]
print(a + b)
# [[5 6 7]
# [6 7 8]
# [7 8 9]]

# broadcast_to 该函数将数组广播到新形状中，它在原始数组的基础上返回一个只读视图。
a = np.arange(4).reshape(1, 4)
print("原数组", a)  # [[0 1 2 3]]
print(np.broadcast_to(a, (4, 4)))
# [[0 1 2 3]
#  [0 1 2 3]
#  [0 1 2 3]
#  [0 1 2 3]]

x = np.array(([1, 2], [3, 4]))
# [[1 2]
# [3 4]]
# 在 0 轴处插入新的轴
y = np.expand_dims(x, axis=0)
# [[[1 2]
#   [3 4]]]
print(x.shape, y.shape)  # (2, 2) (1, 2, 2)

# squeeze 删除数组中维度为 1 的项，
# 例如，一个数组的 shape 是 (5,1)，经此函数后，shape 变为 (5,)
a = np.arange(9).reshape(1, 3, 3)
print(a)
# [[[0 1 2]
#   [3 4 5]
#   [6 7 8]]]
b = np.squeeze(a)
print(b)
# [[0 1 2]
# [3 4 5]
# [6 7 8]]
print('数组 a 和 b 的形状：')
print(x.shape, y.shape)  # (1, 3, 3) (3, 3)

# 连接数组方法
# concatenate	沿指定轴连接两个或者多个相同形状的数组
# stack	沿着新的轴连接一系列数组
# hstack	按水平顺序堆叠序列中数组（列方向）
# vstack	按垂直方向堆叠序列中数组（行方向）
# 分割数组方法
# split	将一个数组分割为多个子数组
# hsplit	将一个数组水平分割为多个子数组（按列）
# vsplit	将一个数组垂直分割为多个子数组（按行）

# 创建数组a
a = np.array([[10, 20], [30, 40]])
print(a)
# 创建数组b
b = np.array([[50, 60], [70, 80]])
print(b)
# 沿轴 0 连接两个数组
print(np.concatenate((a, b)))  # [[10 20] [30 40] [50 60] [70 80]]
# 沿轴 1 连接两个数组
print(np.concatenate((a, b), axis=1))  # [[10 20 50 60] [30 40 70 80]]
# 垂直堆叠
c = np.vstack((a, b))  # [[10 20] [30 40] [50 60] [70 80]]

a = np.arange(6)
# 原数组
print(a)  # [0 1 2 3 4 5]
# 将数组分为二个形状大小相等的子数组
b = np.split(a, 2)
print(b)  # [array([0, 1, 2]), array([3, 4, 5])]
# 将数组在一维数组中标明要位置分割
b = np.split(a, [3, 4])
print(b)  # [array([0, 1, 2]), array([3]), array([4, 5])]

# arr1数组
arr1 = np.floor(10 * np.random.random((2, 6)))
print(arr1)
# [[2. 1. 5. 3. 1. 7.]
#  [1. 2. 9. 0. 9. 9.]]
# 拆分后数组
print(np.hsplit(arr1, 3))
# [array([[2., 1.],
#        [1., 2.]]), array([[5., 3.],
#        [9., 0.]]), array([[1., 7.],
#        [9., 9.]])]]
